//
//  AZURLRouter.m
//  AZURLRouter
//
//  Created by G-Xi0N on 2018/4/3.
//  Copyright © 2018年 gaoX. All rights reserved.
//

#import "AZURLRouter.h"
#import "NSURL+AZURLRouter.h"

@interface AZURLRouterDefaultRedirector : NSObject <AZURLRouterRedirectProtocol>

@end

@implementation AZURLRouterDefaultRedirector

- (void)redirectURL:(NSURL *)url completion:(void (^)(BOOL, NSURL *))completion {
    completion(NO, url);
}

@end

@implementation AZURLRouter

- (instancetype)init
{
    self = [super init];
    if (self) {
        _redirector = [[AZURLRouterDefaultRedirector alloc] init];
    }
    return self;
}

+ (instancetype)sharedURLRouter
{
    static AZURLRouter *router = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        router = [[AZURLRouter alloc] init];
    });
    return router;
}

- (void)openURL:(NSURL *)url
     parameters:(NSDictionary *)parameters
           from:(UIViewController *)from
       animated:(BOOL)animated
  configuration:(void (^)(UIViewController *))configuration
{
    [self.redirector redirectURL:url completion:^(BOOL isRedirected, NSURL *redirectURL) {
        NSDictionary *params = isRedirected ? nil : parameters;
        [self parseURL:redirectURL parameters:params from:from animated:animated configuration:configuration];
    }];
}

- (void)openURL:(NSURL *)url completionHandler:(void (^ _Nullable)(BOOL))completionHandler
{
    if ([[UIApplication sharedApplication] canOpenURL:url]) {
        if (@available(iOS 10.0, *)) {
            [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:completionHandler];
        } else {
            [[UIApplication sharedApplication] openURL:url];
        }
    }
}

- (void)parseURL:(NSURL *)url
      parameters:(NSDictionary *)parameters
            from:(UIViewController *)from
        animated:(BOOL)animated
   configuration:(void (^)(UIViewController *))configuration
{
    if (![url.scheme isEqualToString:@"native"]) {
        [self openURL:url completionHandler:nil];
        return;
    }
    
    NSAssert(url.path.length, @"URL path not found");
    
    NSString *className = [url.path substringFromIndex:1];
    Class class = NSClassFromString(className);
    NSAssert(class, @"Class not found: %@", className);
    
    id target = [[class alloc] init];
    NSAssert(target, @"Class init failed: %@", class);
    NSAssert([target isKindOfClass:UIViewController.class], @"Class type error: %@", target);
    
    UIViewController *to = (UIViewController *)target;
    if (parameters.count > 0) {
        @try {
            [parameters enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
                [to setValue:obj forKeyPath:key];
            }];
        } @catch (NSException *exception) {
            NSLog(@"Set property error");
        } @finally {}
    }
    
    !configuration ?: configuration(to);
    
    [self pushViewControllerFrom:from to:to animated:animated];
}

- (void)pushViewControllerFrom:(UIViewController *)from to:(UIViewController *)to animated:(BOOL)animated
{
    UINavigationController *nav = [from isKindOfClass:[UINavigationController class]] ? (UINavigationController *)from : from.navigationController;
    NSAssert(nav, @"Can't find navigation controller.");
    
    [nav pushViewController:to animated:animated];
}

- (NSURL *)baseURL
{
    return [NSURL URLWithString:@"native://adinnet.cn"];
}

@end
